﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Heyo.Class.Helper.Network;
using HeyoUi;
using HeyoUi.Models.Data.Game;
using HeyoUi.Util;
using KMCCC.Launcher;
using Newtonsoft.Json;
using Version = KMCCC.Launcher.Version;

namespace Heyo.Launcher.Models
{
    /// <summary>
    /// 游戏依赖检查
    /// </summary>
    internal class DependenceInspector
    {
        private class AssetsJson
        {
            [JsonProperty("objects")]
            public Dictionary<string, AssetsItem> Objects { get; set; }

            public class AssetsItem
            {
                [JsonProperty("hash")]
                public string Hash { get; set; }
                [JsonProperty("size")]
                public int Size { get; set; }
            }
        }
        internal class GameDependence
        {
            public GameDependence(string filePath, string downloadUrl, string sha1)
            {
                FilePath = filePath;
                DownloadUrl = downloadUrl;
                Sha1 = sha1;
            }

            public string FilePath { get; }
            public string DownloadUrl { get; }
            public string Sha1 { get; }
        }

        private static string GetAssetsPath(AssetsJson.AssetsItem item)
        {
            return $@"{LauncherBasic.KmcccCore.GameRootPath}\assets\objects\{item.Hash.Substring(0, 2)}\{item.Hash}";
        }

        private static string GetAssetsDownloadUrl(AssetsJson.AssetsItem item)
        {
            const string bmclUrl = "https://bmclapi2.bangbang93.com";
            return $@"{bmclUrl}/objects/{item.Hash.Substring(0, 2)}/{item.Hash}";
        }

        private static string GetLibDownloadUrl(Artifact artifact)
        {
            const bool bmcl = true;
            if (bmcl)
            {
                const string bmclUrl = "https://bmclapi2.bangbang93.com/libraries/";
                return bmclUrl + artifact.Path;
            }
            else
            {
                return artifact.Url;
            }
        }


        private static string GetLibPath(Artifact artifact)
        {
            return $@"{LauncherBasic.KmcccCore.GameRootPath}\libraries\{artifact.Path.Replace("/","\\")}";
        }

        public static IEnumerable<GameDependence> Inspect(LocalGameInfo gameInfo)
        {
            string jsonPath=LauncherBasic.KmcccCore.GetVersionJsonPath(gameInfo.KmcccVersion);
            FileStream gameJsonFs = File.Open(jsonPath,FileMode.Open);
            StreamReader gameJsonReader = new StreamReader(gameJsonFs);
            McGameJson gameJson = JsonConvert.DeserializeObject<McGameJson>(gameJsonReader.ReadToEnd());
            gameJsonFs.Close();
            if (!string.IsNullOrWhiteSpace(gameJson.InheritsFrom))
            {
                string inheritJsonPath = GameLocator.GetJsonPath(gameJson.InheritsFrom);
                gameJsonFs = File.Open(inheritJsonPath, FileMode.Open);
                gameJsonReader = new StreamReader(gameJsonFs);
                McGameJson gameInheritJson = JsonConvert.DeserializeObject<McGameJson>(gameJsonReader.ReadToEnd());
                gameJsonReader.Dispose();
                gameJsonFs.Close();
                List<McLibraries> inLibList =gameJson.Libraries.ToList();
                inLibList.AddRange(gameInheritJson.Libraries);
                gameJson.Libraries = inLibList.ToArray();

                gameJson.AssetIndex = gameInheritJson.AssetIndex;
                gameJson.Assets = gameInheritJson.Assets;
            }
            
            

            //从gameJson.Libraries里面找到缺失的library
            List<GameDependence> dependence = (from lib in gameJson.Libraries
                where lib?.Downloads?.Artifact!=null
                let path = GetLibPath(lib.Downloads.Artifact)
                where !File.Exists(path)
                select new GameDependence(path, GetLibDownloadUrl(lib.Downloads.Artifact), lib.Downloads.Artifact.Sha1)).ToList();

            //兼容forge
            dependence.AddRange((from lib in gameJson.Libraries 
                where lib.Downloads==null
                let path= GameLocator.GetLibPath(lib.Name)
                where !File.Exists(path)
                let url= BmclGetter.GetLibDownloadUrl(lib.Name)
                select new GameDependence(path,url, lib.Checksums?.Length > 0?lib.Checksums[0]:null)));

            //从gameJson.Libraries里面的找classify里到缺失的library
            dependence.AddRange(from lib in gameJson.Libraries
                where lib?.Downloads?.Classifiers!=null
                      && lib.Downloads.Classifiers.ContainsKey("natives-windows")
                let classify= lib.Downloads.Classifiers["natives-windows"]
                let path = GetLibPath(classify)
                where !File.Exists(path)
                select new GameDependence(path, GetLibDownloadUrl(classify),classify.Sha1));

            GameFileInfo assetsIndex = gameInfo.KmcccVersion.AssetsIndex;

            //读取assetsIndex,不存在就下载
            string indexPath = $@"{LauncherBasic.KmcccCore.GameRootPath}\assets\indexes\{assetsIndex.ID}.json";
            if (!File.Exists(indexPath))
            {
                FileDownloader download = new FileDownloader(assetsIndex.Url, indexPath);
                download.Download();
            }

            //读assetsIndex
            string assetsIndexJsonStr;
            FileStream fs = File.Open(indexPath, FileMode.Open);
            using (StreamReader reader= new StreamReader(fs))
            {
                assetsIndexJsonStr = reader.ReadToEnd();
            }
            fs.Close();

            //解析assetsIndex
            AssetsJson assetsJson = JsonConvert.DeserializeObject<AssetsJson>(assetsIndexJsonStr);

            //从assetsIndex里找到不存在的
            dependence.AddRange(from item in assetsJson.Objects.Values
                let path = GetAssetsPath(item)
                where !File.Exists(path)
                select new GameDependence(path, GetAssetsDownloadUrl(item),item.Hash));

            return dependence;
        }
    }
}
